using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DG.Tweening;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.AI;

public class SlotManager : MonoBehaviour
{

    [SerializeField] private bool useMVC;

    private List<Vector3> slotsTargetList = new List<Vector3>();

    private Dictionary<string,Vector2> worldUIMap = new Dictionary<string,Vector2>();

    public readonly List<Vector2> slotsPosList = new ();

    /// <summary>
    /// 消除槽里面的物体 需要清理
    /// </summary>
    /// <typeparam name="Transform"></typeparam>
    /// <returns></returns>
    private List<Transform> slotGameObjList = new List<Transform>();

    /// <summary>
    /// 待消除队列 需要清理
    /// </summary>
    /// <typeparam name="Transform"></typeparam>
    /// <returns></returns>
    
    private Queue<List<Transform>> waitClearList = new Queue<List<Transform>>();
    private bool _isDirty = false;

    /// <summary>
    /// 槽子里面的数据是不是脏数据
    /// 1： 消除的时候
    /// 2： 加入槽子的时候
    /// </summary>
    /// <value></value>
    public bool IsDirty
    {
        get
        {
            return _isDirty;
        }
        set
        {
            _isDirty = value;
            if (value)
            {
                UpdateAllSlots();
            }
        }
    }

    public void Clear() {
        slotGameObjList.Clear();
        waitClearList.Clear();
    }

    /// <summary>
    /// 更新所有的槽位
    /// </summary>
    private void UpdateAllSlots()
    {
        // 赛选掉被标记清除的元素
        slotGameObjList = slotGameObjList.Where((obj) => obj != null && !obj.GetComponent<Toy>().TagClear).ToList();
        Debug.Log($"刷新槽子里面所有物体的位置 {slotGameObjList.Count}");
        IsDirty = false;
    }

    public void UpdateView() {
        for (int i = 0; i < slotGameObjList.Count; i++)
        {
            Transform item = slotGameObjList[i];
            if(item == null) continue;
            Toy toyItem = item.GetComponent<Toy>();
            if (toyItem == null || toyItem.TagClear) continue;
            float targetX = slotsTargetList[i].x;
            item.DOMoveX(targetX, GameConsts.updateViewTime);
        }
    }

    /// <summary>
    /// 更新起始位置之后的节点位置
    /// </summary>
    /// <param name="startIndex"></param> 更新节点位置的起始点
    /// <param name="execAction"></param> 是否立即执行动画
    private void UpdateRemainSlots(int startIndex,bool execAction = true) {
        Debug.LogWarning($"从第{startIndex}更新位置");
        if(startIndex >= GameConsts.slotCount) {
            return;
        }
        for(int i = startIndex; i < slotGameObjList.Count; i++) {
            Transform slotItem = slotGameObjList[i];
            if(slotItem == null) continue;
            Toy toyItme = slotItem.GetComponent<Toy>();
            if(toyItme == null || toyItme.TagClear ) continue;
            float targetX = slotsTargetList[i].x;
            if(execAction) {
                slotItem.DOMoveX(targetX,GameConsts.updateViewTime);
            }
        }
    }

    private void Awake()
    {
        GameManager.Instance().slotManagers = this;
    }

    public bool CheckGameOver() {
        Debug.LogWarning($"槽子里面的物体数量：{slotGameObjList.Count}");
        if(slotGameObjList.Count >= GameConsts.slotCount) {
            GameManager.Instance().game.gameStatus = EGameStatus.GAMEOVER;
            return true;
        }
        return false;
    }

    public int AddToSlots(Transform trs)
    {
        if(trs == null) {
            Debug.LogWarning($"Add trs is null name 2");
            return -1;
        }
        if (slotGameObjList.Count >= GameConsts.slotCount) return - 1;
        if (!slotGameObjList.Contains(trs))
        {
            // 找到同类型的3d物体
            int lastSameTypeIndex = FindLastSameTypeObject(trs);
            if (lastSameTypeIndex > -1)
            {
                int targetIndex = lastSameTypeIndex + 1;
                // 修改了物体排列数据
                slotGameObjList.Insert(targetIndex, trs);
                // 数据更新了需要重新排列
                UpdateRemainSlots(targetIndex + 1);
                // 找到一个跟它同类型的物体 它后面的物体往后放
                return targetIndex;
            }
            else
            {
                // 没有相同类型的物体返回最后一个位置
                slotGameObjList.Add(trs);
                return slotGameObjList.Count - 1;
            }
        }
        Debug.LogWarning($"列表里面有了");
        return -1;
    }

    /// <summary>
    /// 找出最后一个和传入类型相同的物体索引
    /// </summary>
    /// <param name="trs"></param>
    /// <returns></returns>
    private int FindLastSameTypeObject(Transform trs)
    {
        int right = slotGameObjList.Count - 1;

        while (right >= 0)
        {
            if (slotGameObjList[right] == null)
            {
                Debug.Log($"{right}位置上的物体为空");
                right--;
                continue;
            }
            if (slotGameObjList[right].name == trs.name)
            {
                return right;
            }
            right--;
        }
        return right;
    }

    /// <summary>
    /// 检查是否可以消除，滑动窗口的方式查找如果窗口内都是相同的类型就扩大窗口，遇到一个不同类型的时候窗口缩小
    /// </summary>
    /// <returns></returns>
    public bool CheckCanClear()
    {
        bool canClear = false;
        if (slotGameObjList.Count < 3) return canClear;

        string clearType = "";

        List<Transform> clearWindow = new();
        for (int i = 0; i < slotGameObjList.Count; i++)
        {
            Transform transformItem = slotGameObjList[i];
            if(transformItem == null) {
                Debug.LogWarning($"Error 位置{i}");
                IsDirty = true;
                UpdateView();
                continue;
            }
            Toy toyItem = transformItem.GetComponent<Toy>();
            if (transformItem.name != clearType)
            {
                clearType = transformItem.name;
                clearWindow.Clear();
                clearWindow.Add(transformItem);
            }
            else
            {
                // 还在路上
                if (!toyItem.IsInSlot) continue;
                // 已经进入槽子了
                clearWindow.Add(transformItem);
                if (clearWindow.Count >= 3)
                {
                    List<Transform> list = new List<Transform>();

                    for (int j = 0; j < clearWindow.Count; j++)
                    {
                        Toy clearItem = clearWindow[j].GetComponent<Toy>();
                        // 标记为带清楚状态
                        clearItem.TagClear = true;
                        // 将该元素从槽子里移除
                        list.Add(clearWindow[j]);
                    }
                    waitClearList.Enqueue(list);
                    clearWindow.Clear();
                }
            }
        }

        canClear = waitClearList.Count >= 1;

        if (canClear)
        {
            Debug.Log("可以消除。。。");
            AndroidUtils.Vibrate(200);
            GameManager.Instance().game.Score += GameConsts.scorePerClear * GameManager.Instance().uiManager.ScoreRatio;
            EventManager.Instance.Pub("clear");
            // 更新数据
            IsDirty = true;
            GameManager.Instance().audioManager.PlayAudio(EAudioType.GOAL);
            // 执行消除动作协程
            StartCoroutine(ExecClearAction());
        }

        return canClear;

    }

    /// <summary>
    ///  移动到消除中心然后执行消除动作
    /// </summary>
    /// <param name="trs"></param>
    /// <returns></returns>
    private IEnumerator MoveCenterAndClear(List<Transform> trs)
    {
        Transform firstTrs = trs[0];
        Transform centerTrs = trs[1];
        Transform lastTrs = trs[2];

        float centerX = centerTrs.position.x;

        Toy firstToy = firstTrs.GetComponent<Toy>();
        Toy centerToy = centerTrs.GetComponent<Toy>();
        Toy lastToy = lastTrs.GetComponent<Toy>();

        StartCoroutine(firstToy.MoveToClearCenter(centerX));
        GameManager.Instance().effectManager.PlayClearEffect(centerTrs.position);
        Vector3 p = PositionUtils.twoSem(centerTrs.position);
        Vector2 screenPos = worldUIMap.GetValueOrDefault($"{p.x}_{p.z}");
        // 开启播放特效协程
        StartCoroutine(GameManager.Instance().topUI.ShowStarEffect(screenPos,GameManager.Instance().game.Score));
        yield return StartCoroutine(lastToy.MoveToClearCenter(centerX));

        StartCoroutine(firstToy.ClearAction());
        StartCoroutine(centerToy.ClearAction());
        yield return StartCoroutine(lastToy.ClearAction());
    }

    /// <summary>
    /// 执行消除动作 异步执行
    /// </summary>
    private IEnumerator ExecClearAction()
    {
        while(waitClearList.Count > 0) {
            List<Transform> list = waitClearList.Dequeue();
            yield return MoveCenterAndClear(list);
        }
        // 消除完毕标记数据是脏的需要更新视图
        UpdateView();
        bool isOver = GameManager.Instance().game.CheckAllToyLosted();
        Debug.LogWarning($"所有的东西是否消除完毕{isOver}");
        if(isOver) {
            // 游戏完毕，判断输赢
            GameManager.Instance().game.gameStatus = EGameStatus.GAMEOVER;
        }

    }

    public bool IsWin() {
        return slotGameObjList.Count == 0;
    }

    public Vector3 SlotTargetWorldPosByIndex(int index)
    {
        if (index >= 0 && index <= 6)
        {
            return slotsTargetList[index];

        }
        return Vector3.zero;
    }

    public void Init()
    {
        float targetAspect = (float)750 / (float)1334;
        float screenAspect = (float)Screen.width / (float)Screen.height;

        float ratio = screenAspect / targetAspect;

        for (int i = 0; i < transform.childCount; i++)
        {
            Transform child = transform.GetChild(i);

            RectTransform rtItem = child.GetComponent<RectTransform>();
            Debug.Log($"rtItem position is " + rtItem.position);

            if (rtItem != null)
            {
                Vector3 tp = new(rtItem.position.x * ratio, rtItem.position.y, rtItem.position.z * ratio);
                Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(Camera.main,rtItem.position);
                Debug.Log("screenPos is " + screenPos);
                Debug.Log("real tp is " + tp);
                slotsTargetList.Add(tp);
                tp.GetHashCode();
                Vector3 t = PositionUtils.twoSem(tp);
                string key = $"{t.x}_{t.z}";
                worldUIMap.Add(key,screenPos);
                slotsPosList.Add(screenPos);
            }
            else
            {
                Debug.LogWarning("Child does not have a RectTransform component.");
            }
        }
        Debug.Log("list is " + slotsTargetList);
    }

    // Start is called before the first frame update
    void Start()
    {
        Init();
    }

}
